<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {font-family: Arial;}

/* Style the tab */
.tab {
  overflow: hidden;
  border: 1px solid #ccc;
  background-color: #f1f1f1;
}

/* Style the buttons inside the tab */
.tab button {
  background-color: inherit;
  float: left;
  border: none;
  outline: none;
  cursor: pointer;
  padding: 14px 16px;
  transition: 0.3s;
  font-size: 17px;
}

/* Change background color of buttons on hover */
.tab button:hover {
  background-color: #ddd;
}

/* Create an active/current tablink class */
.tab button.active {
  background-color: #ccc;
}

/* Style the tab content */
.tabcontent {
  display: none;
  padding: 6px 12px;
  border: 1px solid #ccc;
  border-top: none;
}

/* Fieldset and Legend */
fieldset {
    margin: 8px;
    border: 1px solid silver;
    padding: 8px;    
    border-radius: 4px;
}

legend {
    padding: 2px;    
}

/* Two columns */
.container_two_column * {
  box-sizing: border-box;
}

/* Create two equal columns that floats next to each other */
.column_left {
  float: left;
  width: 50%;
  padding: 10px;
}

.column_right {
  float: left;
  width: 50%;
  padding: 10px;
}

/* Clear floats after the columns */
.container_two_column:after {
  content: "";
  display: table;
  clear: both;
}

/* Responsive layout - makes the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
  .column_left {
    width: 100%;
  }
  
  .column_right {
    width: 100%;
  }
}


</style>
</head>


<body>

<title>Modbus RTU2TCP Configuration</title>
<h2>Modbus RTU2TCP Configuration</h2>

<!-- Tab Control -->
<div class="tab">
  <button class="tablinks" onclick="openTab(event, 'wifi')" id="defaultOpen">Wifi</button>
  <button class="tablinks" onclick="openTab(event, 'uart')">Uart</button>
  <button class="tablinks" onclick="openTab(event, 'log')">Log</button>
  <!-- <button class="tablinks" onclick="openTab(event, 'ota')">OTA</button>  -->
  <button class="tablinks" onclick="openTab(event, 'about')">About</button>
</div>

<div id="wifi" class="tabcontent">
	<label for="wifi_mode">Wifi mode:</label><br>
	<select id="wifi_mode">
	    <option value = "0">AP mode only</option>
	    <option value = "1">Prefer STA mode, AP mode as backup</option>
	</select>
	<br>
	<br>
	

	<fieldset> <legend>Wifi Station Mode</legend>
		<div class="container_two_column">
			<div class="column_left">
				<label for="wifi_sta_ssid">Wifi SSID:</label><br>
				<input type="text" id="wifi_sta_ssid"><br>
				<label for="wifi_sta_pass">Wifi Password:</label><br>
				<input type="text" id="wifi_sta_pass"><br>
				<label for="wifi_sta_retry">No. of reconnection before switch enable AP mode:</label><br>
				<input type="text" id="wifi_sta_retry"><br>
				<br>
				<button onclick="wifiConnect()">Connect</button><button onclick="wifiDisconnect()">Disconnect</button><br>
  			</div>
  			<div class="column_right" style="background-color:#bbb;">
				<label>Wifi station status:</label><br>
				<div id="wifi_sta_status" style="white-space: pre-wrap;"></div>
  			</div>
		</div>
	</fieldset>

	<fieldset> <legend>Wifi AP Mode</legend>
		<div class="container_two_column">
			<div class="column_left">
				<label for="wifi_ap_ssid">AP Mode SSID:</label><br>
				Leave empty to use the default SSID (Modbus RTU2TCP [MAC])<br>
				<input type="text" id="wifi_ap_ssid"><br>
				<label for="wifi_ap_pass">AP Mode Password:</label><br>
				<input type="text" id="wifi_ap_pass"><br>
				<label for="wifi_ap_auth">AP Auth Mode:</label><br>
				<select id="wifi_ap_auth">
				    <option value = "0">Open, No password</option>
				    <option value = "1">WEP</option>
				    <option value = "2">WPA_PSK</option>
				    <option value = "3">WPA2_PSK</option>
				    <option value = "4">WPA_WPA2_PSK</option>
				    <option value = "5">WPA2_ENTERPRISE</option>
				    <option value = "6">WPA3_PSK</option>
				    <option value = "7">WPA2_WPA3_PSK</option>
				</select><br>
				<label for="wifi_ap_conn">AP Max No. of Clients:</label><br>
				<input type="text" id="wifi_ap_conn"><br>
				<br>
				<button onclick="apTurnOn()">Turn on</button><button onclick="apTurnOff()">Turn off</button><br>
  			</div>
  			<div class="column_right" style="background-color:#bbb;">
  				<label>Wifi AP status:</label><br>
				<div id="wifi_ap_status" style="white-space: pre-wrap;"></div>
		  	</div>
		</div>
	</fieldset>
	<br>
	<p style="color:red">In order to prevent lost of access, DO NOT disconnect from the external AP and switch off the built-in AP at the same time. </p>
</div>

<div id="uart" class="tabcontent">
	<label for="uart_baud_rate">Baud rate:</label><br>
	<select id="uart_baud_rate">
	    <option>2400</option>
	    <option>4800</option>
	    <option>9600</option>
	    <option>14400</option>
	    <option>19200</option>
	    <option>28800</option>
	    <option>38400</option>
	    <option>57600</option>
	    <option>115200</option>
	    <option>128000</option>
	    <option>256000</option>
	    <option>921600</option>
	</select><br>
	<label for="uart_parity">Parity:</label><br>
	<select id="uart_parity">
	    <option value="0">None</option>
	    <option value="1">Odd</option>
	    <option value="2">Even</option>
	</select><br>
	<label for="uart_tx_delay">Tx Delay(us):</label><br>
	<input type="text" id="uart_tx_delay" name="uart_tx_delay"><br><br>
</div>

<div id="log" class="tabcontent">
	<button onclick="clearJsonLog()">Clear JSON Log</button>
	<fieldset> <legend>JSON Log</legend>
		<div id="json_log" style="white-space: pre-wrap;">
		</div>
	</fieldset>
</div>

<div id="ota" class="tabcontent">
	<label>Firmware Upgrade</label><br>
	<fieldset> <legend>ESP8266</legend>
		<label for="ota_esp8266_bin">URL of the new firmware (HTTP only):</label><br>
		<input type="file" id="ota_esp8266_bin" name="fileContent"><br>
		<button onclick="otaESP8266()">Upload and Start</button>
	</fieldset>
</div>

<div id="about" class="tabcontent">
	<img src="https://github.com/rikka0w0.png?size=460"><br>
	Designed by <a href="https://github.com/rikka0w0/">Rikka0w0</a>.<br>
	<a href="https://github.com/rikka0w0/modbus_rtu2tcp/">Github Repo</a> of this Project<br>
	<br>
	For help and documentations, please visit <a href="https://github.com/rikka0w0/modbus_rtu2tcp/wiki">the Wiki</a>.<br>
	Please feel free to submit bug reports and any suggestion to <a href="https://github.com/rikka0w0/modbus_rtu2tcp/issues">the issue tracker</a>.<br>
</div>

<script>
function openTab(evt, cityName) {
	var i, tabcontent, tablinks;
	tabcontent = document.getElementsByClassName("tabcontent");
	for (i = 0; i < tabcontent.length; i++) {
		tabcontent[i].style.display = "none";
	}
	tablinks = document.getElementsByClassName("tablinks");
	for (i = 0; i < tablinks.length; i++) {
		tablinks[i].className = tablinks[i].className.replace(" active", "");
	}
	document.getElementById(cityName).style.display = "block";
	evt.currentTarget.className += " active";
}
document.getElementsByClassName("tablinks")[0].click();
</script>
<!-- End of Tab Control -->

<br>

<button onclick="applySettings()">Save Configuration</button>

<form action="/restart?confirm=yes">
	<input type="submit" value="Restart" />
	<input type="checkbox" id="confirm" name="confirm" value="yes">Confirm restart</input>
</form>
<br>

<script>
var debug = true;
var fields = ["wifi_sta_ssid", "wifi_sta_pass", "wifi_sta_retry", "wifi_ap_ssid", "wifi_ap_pass", "wifi_ap_auth", "wifi_ap_conn", "wifi_mode", "uart_baud_rate", "uart_parity", "uart_tx_delay"];

function canLog(method) {
	return debug && method != "wifi_sta_status" && method != "wifi_ap_status";
}

// Handlers
function updateFields(resp) {
	fields.forEach(function(key) {
		document.getElementById(key).value = resp[key];
	});
}

function updateStaStatus(resp) {
	var old = document.getElementById("wifi_sta_status").innerText;
	var txt;
	if (resp["wifi_sta_status"] == "connected") {
		txt = "Connected to: \"" + resp["wifi_sta_ap_ssid"] +"\"\n";
		txt += "IPv4 Address: \"" + resp["wifi_sta_ip4_address"] +"\"\n";
		txt += "IPv4 Netmask: \"" + resp["wifi_sta_ip4_netmask"] +"\"\n";
		txt += "IPv4 Gateway: \"" + resp["wifi_sta_ip4_gateway"] +"\"\n";
		resp["wifi_sta_ip6_address"] .forEach(function(addr) {
			txt += "IPv6 Address: \"" + addr +"\"\n";
		});
	} else {
		 txt = resp["wifi_sta_status"];
	}

	if (txt != old) {
		document.getElementById("wifi_sta_status").innerText = txt;
	}
}

function updateApStatus(resp) {
	var old = document.getElementById("wifi_ap_status").innerText;
	var txt;
	if (resp["wifi_ap_turned_on"]) {
		txt = "Broadcasting with SSID \"" + resp["wifi_ap_ssid"] +"\"\n";
		txt += "IPv4 Address: \"" + resp["wifi_ap_ip4_address"] +"\"\n";
		txt += "IPv4 Netmask: \"" + resp["wifi_ap_ip4_netmask"] +"\"\n";
		txt += "IPv4 Gateway: \"" + resp["wifi_ap_ip4_gateway"] +"\"\n";
		resp["wifi_ap_ip6_address"] .forEach(function(addr) {
			txt += "IPv6 Address: \"" + addr +"\"\n";
		});
	} else {
		 txt = "Turned off";
	}

	if (txt != old) {
		document.getElementById("wifi_ap_status").innerText = txt;
	}	
}

// XMLHttpRequest queue
var xhttpQueue = new Array();
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
	if (this.readyState != 4)
		return;

	if (this.status == 200) {
		var resp = JSON.parse(xhttp.responseText);

		if (canLog(resp["method"])) {
			document.getElementById("json_log").textContent += "<<<<<<<<<<<<<<<<<<<<<<<<<<";
			document.getElementById("json_log").textContent += "\n";
			document.getElementById("json_log").textContent += xhttp.responseText;
			document.getElementById("json_log").textContent += "\n";
		}

		if (resp["method"] === "get") {
			updateFields(resp);
		} else if (resp["method"] === "wifi_sta_status") {
			updateStaStatus(resp);
		} else if (resp["method"] === "wifi_ap_status") {
			updateApStatus(resp);
		}
	}

	xhttpQueue.shift();
	if (xhttpQueue.length > 0) {
		var req = xhttpQueue[0];
		xhttp_send_internal(req["method"], req["payload"]);
	}
};

function xhttp_send_internal(method, json_payload) {
	if (method === "get") {
		xhttp.open("get", "/json_get?json=" + encodeURIComponent(JSON.stringify(json_payload)) + "&test=qwq", true);
		xhttp.send();
	} else if (method === "post") {
		xhttp.open("post", "/json_post", true);
		xhttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
		xhttp.send(JSON.stringify(json_payload));
	}
}

function xhttp_send(method, json_payload) {
	var req = {};
	req["method"] = method;
	req["payload"] = json_payload;
	xhttpQueue.push(req);

	if (xhttpQueue.length == 1) {
		xhttp_send_internal(method, json_payload);
	}
	
	if (canLog(json_payload["method"])) {
		document.getElementById("json_log").textContent += ">>>" + method + ">>>>>>>>>>>>>>>>>";
		document.getElementById("json_log").textContent += "\n";
		document.getElementById("json_log").textContent += JSON.stringify(json_payload);
		document.getElementById("json_log").textContent += "\n";
	}
}

// Button callbacks
function clearJsonLog() {
	document.getElementById("json_log").textContent = "";
}

function applySettings() {
	var json_req = {method: "set", fields: {}};
	var fields_req = json_req["fields"];
	fields.forEach(function(key) {
		fields_req[key] = document.getElementById(key).value;
	});
	xhttp_send("post", json_req);
}

function wifiConnect() {
	var json_req = {method: "wifi_sta_connect"};
	json_req["wifi_sta_ssid"] = document.getElementById("wifi_sta_ssid").value;
	json_req["wifi_sta_pass"] = document.getElementById("wifi_sta_pass").value;
	xhttp_send("get", json_req);
}

function wifiDisconnect() {
	var json_req = {method: "wifi_sta_disconnect"};
	xhttp_send("get", json_req);
}

function apTurnOn() {
	var json_req = {method: "wifi_ap_on"};
	xhttp_send("get", json_req);
}

function apTurnOff() {
	var json_req = {method: "wifi_ap_off"};
	xhttp_send("get", json_req);
}

function otaESP8266() {
	var file = document.getElementById("ota_esp8266_bin").files[0];
	if(!!file) {
		var reader = new FileReader();
		reader.readAsArrayBuffer(file);
		reader.onload = function() {
			var xhr = new XMLHttpRequest();
			xhr.open("post", "/ota_post", true);
			xhr.overrideMimeType("Content-Type", "application/octet-stream");
    		xhr.send(this.result);
		}
	}
}

function readSettings() {
	var json_req = {method: "get", fields: []};
	fields.forEach(function(key) {
		json_req["fields"].push(key);
	});
	xhttp_send("get", json_req);
}

function readStaStatus() {
	var json_req = {method: "wifi_sta_status"};
	xhttp_send("get", json_req);
}

function readApStatus() {
	var json_req = {method: "wifi_ap_status"};
	xhttp_send("get", json_req);
}


readSettings();
readStaStatus();
setInterval(readStaStatus, 1000);
setInterval(readApStatus, 1000);
</script>

</body>
</html>